home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / SLIP.C < prev    next >
C/C++ Source or Header  |  1990-07-22  |  7KB  |  308 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #include "asy.h"
  11. #include "combios.h"
  12. #include "trace.h"
  13.  
  14. /* Slip level control structure */
  15. struct slip slip[ASY_MAX];
  16.  
  17. static int asy_start();
  18.  
  19. /* Send routine for point-to-point slip
  20.  * This is a trivial function since there is no slip link-level header
  21.  */
  22. int
  23. slip_send(data,interface,gateway,precedence,delay,throughput,reliability)
  24. struct mbuf *data;        /* Buffer to send */
  25. struct interface *interface;    /* Pointer to interface control block */
  26. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  27. char precedence;
  28. char delay;
  29. char throughput;
  30. char reliability;
  31. {
  32.     if(interface == NULLIF){
  33.         free_p(data);
  34.         return -1;
  35.     }
  36.     dump(interface,IF_TRACE_OUT,TRACE_IP,data);
  37.     return (*interface->raw)(interface,data);
  38. }
  39. /* Send a raw slip frame -- also trivial */
  40. int
  41. slip_raw(interface,data)
  42. struct interface *interface;
  43. struct mbuf *data;
  44. {
  45.     /* Queue a frame on the slip output queue and start transmitter */
  46.     return slipq(interface->dev,data);
  47. }
  48. /* Encode a raw packet in slip framing, put on link output queue, and kick
  49.  * transmitter
  50.  */
  51. static int
  52. slipq(dev,data)
  53. int16 dev;        /* Serial line number */
  54. struct mbuf *data;    /* Buffer to be sent */
  55. {
  56.     register struct slip *sp;
  57.     struct mbuf *slip_encode(),*bp;
  58.  
  59.     if((bp = slip_encode(data)) == NULLBUF)
  60.         return -1;
  61.  
  62.     sp = &slip[dev];
  63.     enqueue(&sp->sndq,bp);
  64.     sp->sndcnt++;
  65.     if(sp->tbp == NULLBUF)
  66.         asy_start(dev);
  67.     return 0;
  68. }
  69. /* Start output, if possible, on asynch device dev */
  70. static int
  71. asy_start(dev)
  72. int16 dev;
  73. {
  74.     register struct slip *sp;
  75.     int asy_output();
  76. #ifdef    COMBIOS
  77.     struct com *cp;
  78.     unsigned char c;
  79.     unsigned stat;
  80.     int numsend;
  81. #endif
  82.  
  83. #ifdef    COMBIOS
  84.     com[dev].stat |= (stat = combios(0x0300,dev));
  85.     if(!(stat & 0x2000))
  86. #else
  87.     if(!stxrdy(dev))
  88. #endif
  89.         return -1;    /* Transmitter not ready */
  90.  
  91.     sp = &slip[dev];
  92.  
  93.     if(sp->tbp != NULLBUF){
  94. #ifdef    COMBIOS
  95.         goto comsend;    /* still something to send */
  96. #else
  97.         /* transmission just completed */
  98.         free_p(sp->tbp);
  99.         sp->tbp = NULLBUF;
  100. #endif
  101.     }
  102.  
  103.     if(sp->sndq == NULLBUF)
  104.         return 0;    /* No work */
  105.  
  106.     sp->tbp = dequeue(&sp->sndq);
  107.     sp->sndcnt--;
  108.  
  109. #ifdef    COMBIOS
  110. comsend:
  111.     cp = &com[dev];                /* quick ptr to our com */
  112.  
  113.     if ((numsend = cp->txbuf) == 0)
  114.         numsend = cp->speed;        /* enough for 10 seconds */
  115.  
  116.     while(--numsend && pullup(&sp->tbp,&c,1) == 1) {
  117.         cp->stat |= (stat = combios(0x0100 | c,dev)) & 0x7f00;
  118.         if (cp->txbuf == 0 &&        /* no explicit tx buffer max */
  119.             (stat & 0xa000) != 0x2000)    /* timeout or full */
  120.             break;
  121.     }
  122. #else
  123.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  124. #endif
  125.     return 1;
  126. }
  127. /* Encode a packet in SLIP format */
  128. struct mbuf *
  129. slip_encode(bp)
  130. struct mbuf *bp;
  131. {
  132.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  133.     register char *cp;
  134.     char c;
  135.  
  136.     /* Allocate output mbuf that's twice as long as the packet.
  137.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  138.      */
  139.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  140.     if(lbp == NULLBUF){
  141.         /* No space; drop */
  142.         free_p(bp);
  143.         return NULLBUF;
  144.     }
  145.     cp = lbp->data;
  146.  
  147.     /* Flush out any line garbage */
  148.     *cp++ = FR_END;
  149.  
  150.     /* Copy input to output, escaping special characters */
  151.     while(pullup(&bp,&c,1) == 1){
  152.         switch(uchar(c)){
  153.         case FR_ESC:
  154.             *cp++ = FR_ESC;
  155.             *cp++ = T_FR_ESC;
  156.             break;
  157.         case FR_END:
  158.             *cp++ = FR_ESC;
  159.             *cp++ = T_FR_END;
  160.             break;
  161.         default:
  162.             *cp++ = c;
  163.         }
  164.     }
  165.     *cp++ = FR_END;
  166.     lbp->cnt = cp - lbp->data;
  167.     return lbp;
  168. }
  169. /* Process incoming bytes in SLIP format
  170.  * When a buffer is complete, return it; otherwise NULLBUF
  171.  */
  172. struct mbuf *
  173. slip_decode(sp,c)
  174. register struct slip *sp;    /* Slip level control struct */
  175. char c;                /* Incoming character */
  176. {
  177.     struct mbuf *bp;
  178.  
  179.     switch(uchar(c)){
  180.     case FR_END:
  181.         bp = sp->rbp;
  182.         sp->rbp = NULLBUF;
  183.         sp->rcnt = 0;
  184.         return bp;    /* Will be NULLBUF if empty frame */
  185.     case FR_ESC:
  186.         sp->escaped = 1;
  187.         return NULLBUF;
  188.     }
  189.     if(sp->escaped){
  190.         /* Translate 2-char escape sequence back to original char */
  191.         sp->escaped = 0;
  192.         switch(uchar(c)){
  193.         case T_FR_ESC:
  194.             c = FR_ESC;
  195.             break;
  196.         case T_FR_END:
  197.             c = FR_END;
  198.             break;
  199.         default:
  200.             sp->errors++;
  201.             break;
  202.         }
  203.     }
  204.     /* We reach here with a character for the buffer;
  205.      * make sure there's space for it
  206.      */
  207.     if(sp->rbp == NULLBUF){
  208.         /* Allocate first mbuf for new packet */
  209.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  210.             return NULLBUF; /* No memory, drop */
  211.         sp->rcp = sp->rbp->data;
  212.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  213.         /* Current mbuf is full; link in another */
  214.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  215.             /* No memory, drop whole thing */
  216.             free_p(sp->rbp);
  217.             sp->rbp = NULLBUF;
  218.             sp->rcnt = 0;
  219.             return NULLBUF;
  220.         }
  221.         sp->rbp1 = sp->rbp1->next;
  222.         sp->rcp = sp->rbp1->data;
  223.     }
  224.     /* Store the character, increment fragment and total
  225.      * byte counts
  226.      */
  227.     *sp->rcp++ = c;
  228.     sp->rbp1->cnt++;
  229.     sp->rcnt++;
  230.     return NULLBUF;
  231. }
  232. /* Process SLIP line I/O */
  233. int
  234. doslip(interface)
  235. struct interface *interface;
  236. {
  237. #ifdef    COMBIOS
  238.     unsigned stat;
  239. #else
  240.     char c;
  241. #endif
  242.     struct mbuf *bp;
  243.     register struct slip *sp;
  244.     int16 dev;
  245.     int rv = 0;
  246.     int16 asy_recv();
  247.  
  248.     dev = interface->dev;
  249.     sp = &slip[dev];
  250.  
  251. #ifdef    COMBIOS
  252.     /* Process any pending input */
  253. fossil:
  254.     com[dev].stat |= (stat = combios(0x0300,dev));
  255.  
  256.     while(stat & 0x0100) {
  257.         com[dev].stat |= (stat = combios(0x0200,dev));
  258.  
  259.         if((bp = slip_decode(sp,stat & 0xff)) != NULLBUF) {
  260.             if (com[dev].stat & 0x1a00)    /* error detected? */
  261.                 free(bp);        /* discard frame */
  262.             else
  263.                 (*sp->recv)(interface,bp);
  264.  
  265.             com[dev].stat = 0;
  266.             rv++;
  267.         }
  268.  
  269.         if(com[dev].drtype == 3)
  270.             goto fossil;        /* FOSSIL needs new status */
  271.     }
  272.  
  273.     /* Kick the transmitter if it's idle */
  274.     if(stat & 0x2000)
  275.         if (asy_start(dev))
  276.             rv++;
  277. #else
  278.     /* Process any pending input */
  279.     while(asy_recv(dev,&c,1) != 0)
  280.         if((bp = slip_decode(sp,c)) != NULLBUF){
  281.             (*sp->recv)(interface,bp);
  282.             rv++;
  283.         }
  284.  
  285.     /* Kick the transmitter if it's idle */
  286.     if(sp->sndq != NULLBUF){
  287.         asy_start(dev);
  288.         rv++;
  289.     }
  290. #endif
  291.  
  292.     return rv;                /* processed packets */
  293. }
  294. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  295.  * link level header
  296.  */
  297. void
  298. slip_recv(interface,bp)
  299. struct interface *interface;
  300. struct mbuf *bp;
  301. {
  302.     int ip_route();
  303.  
  304.     /* By definition, all incoming packets are "addressed" to us */
  305.     dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  306.     ip_route(bp,0);
  307. }
  308.